home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / source / hotspot / editor / drawhot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-03  |  12.2 KB  |  449 lines

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (c) 1993  Microsoft Corporation.  All Rights Reserved.
  9.  * 
  10.  **************************************************************************/
  11.  
  12.  
  13. /*
  14.  * This file contains an AVI DrawProc, and various functions that the
  15.  * DrawProc calls (see the list of forward declars for a list of these
  16.  * functions; the ICAVIDrawProc is the only function visible outside
  17.  * this file).
  18.  *
  19.  * The drawproc draws red rectangles on an AVI to represent hotspots.
  20.  * The drawproc also slows down the AVI playback, because it copies the
  21.  * entire image onto a device-dependent bitmap for drawing the rectangles
  22.  *
  23.  */
  24.  
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <vfw.h>
  28.  
  29. #include "hotspot.h"
  30.  
  31. // unfortunately I had to use a global variable to get this to work.
  32. extern PMOVIEINFO pMovieInfo;
  33.  
  34. // junk for AVIDrawGetInfo
  35. #define SZCODE char _based(_segname("_CODE"))
  36. static SZCODE szDescription[] = "Microsoft Hotspot Draw handler";
  37. static SZCODE szName[]        = "MS Hotspot";
  38. #define FOURCC_AVIDraw      mmioFOURCC('H','O','T','T')
  39. #define VERSION_AVIDraw     0x00010000
  40.  
  41. #ifndef HUGE
  42. #define HUGE _huge
  43. #endif
  44.  
  45. // this is the structure that video for windows hangs on to for us.
  46. // We allocate it and give vfw a pointer when the drawproc is
  47. // opened, and it gives it back while the frames are being drawn.
  48. // We store such things as our DC and our pen to draw the rectangles
  49. // with in here.
  50. typedef struct
  51. {
  52.     HDRAWDIB            hdd;
  53.     HDC                 hdc;
  54.     int                 xDst;
  55.     int                 yDst;
  56.     int                 dxDst;
  57.     int                 dyDst;
  58.     int                 xSrc;
  59.     int                 ySrc;
  60.     int                 dxSrc;
  61.     int                 dySrc;
  62.     HBITMAP                hddb;
  63.     HDC                    hMemdc;
  64.     HBITMAP                hOldbmp;
  65.     HBRUSH                hBrush;
  66.     HBRUSH                hOldBrush;
  67.     HPEN                hPen;
  68.     HPEN                hOldPen;
  69.     PMOVIEINFO            lpMovie;
  70. } INSTINFO, FAR * PINSTINFO;
  71.  
  72.  
  73. // forward declars
  74. LONG FAR PASCAL _export ICAVIDrawProc(DWORD id, HDRVR hDriver,
  75.     UINT uiMessage, LPARAM lParam1, LPARAM lParam2);
  76. static LONG NEAR PASCAL AVIDrawOpen(ICOPEN FAR * icopen);
  77. static LONG NEAR PASCAL AVIDrawClose(PINSTINFO pi);
  78. static LONG NEAR PASCAL AVIDrawGetInfo(ICINFO FAR *icinfo, LONG lSize);
  79. static LONG NEAR PASCAL AVIDrawQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn);
  80. static LONG NEAR PASCAL AVIDrawSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd);
  81. static LONG NEAR PASCAL AVIDrawBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd);
  82. static LONG NEAR PASCAL AVIDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd);
  83. static LONG NEAR PASCAL AVIDrawEnd(PINSTINFO pi);
  84. static LONG NEAR PASCAL AVIDrawChangePalette(PINSTINFO pi, LPBITMAPINFOHEADER lpbi);
  85.  
  86. // macros used by DIB stuff.
  87. // hey, we're not using DIB stuff anymore...
  88. #define WIDTHBYTES(i)     ((unsigned)((i+31)&(~31))/8)
  89. #define DIBWIDTHBYTES(bi) (DWORD)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
  90.  
  91. // Here we create a device-dependent bitmap in memory to draw into.
  92. // We'll copy the DIB onto this bitmap, draw rects on it, then copy
  93. // the result to the screen.  This can be done more efficiently using
  94. // the DIB driver that comes with Windows 3.1, if anybody wants to 
  95. // recode it...
  96. // We also create our red pen here, as well as a brush for doing
  97. // =hollow= rectangles
  98. void CreateMemoryDC(PINSTINFO pi)
  99. {
  100.     LOGBRUSH lb;
  101.     pi->hddb = CreateCompatibleBitmap(pi->hdc,pi->dxDst,pi->dyDst);
  102.     pi->hMemdc = CreateCompatibleDC(pi->hdc);
  103.     pi->hOldbmp = SelectObject(pi->hMemdc,pi->hddb);
  104.     lb.lbStyle = BS_NULL;
  105.     pi->hBrush = CreateBrushIndirect(&lb);
  106.     pi->hOldBrush = SelectObject(pi->hMemdc,pi->hBrush);
  107.     pi->hPen = CreatePen(PS_SOLID,0,RGB(255,0,0));
  108.     pi->hOldPen = SelectObject(pi->hMemdc,pi->hPen);
  109. }
  110.  
  111. // here we undo everything CreateMemoryDC did.
  112. void DisintegrateMemoryDC(PINSTINFO pi)
  113. {
  114.     SelectObject(pi->hMemdc,pi->hOldPen);
  115.     DeleteObject(pi->hPen);
  116.     SelectObject(pi->hMemdc,pi->hOldBrush);
  117.     DeleteObject(pi->hBrush);
  118.     SelectObject(pi->hMemdc,pi->hOldbmp);
  119.     DeleteObject(pi->hddb); pi->hddb = NULL;
  120.     DeleteDC(pi->hMemdc); pi->hMemdc = NULL;
  121. }
  122.  
  123. // this is the drawproc that vfw calls.  It basically just hands
  124. // stuff off to other functions later in this file.  A few things
  125. // are handled here.  This is message-handling proc just like a
  126. // Window Proc or a VBX Control Proc...
  127. LONG FAR PASCAL _export ICAVIDrawProc(DWORD id, HDRVR hDriver,
  128.     UINT uiMessage, LPARAM lParam1, LPARAM lParam2)
  129. {
  130.     PINSTINFO pi = (PINSTINFO)id;
  131.     switch (uiMessage)
  132.     {
  133.     case DRV_LOAD:
  134.     case DRV_FREE:
  135.         return 1;
  136.     case DRV_OPEN:
  137.         if (lParam2 == 0L)
  138.         {
  139.             return 1;
  140.         }
  141.         return AVIDrawOpen((ICOPEN FAR *)lParam2);
  142.     case DRV_CLOSE:
  143.         return AVIDrawClose(pi);
  144.     case DRV_QUERYCONFIGURE:
  145.         return 0;
  146.     case DRV_CONFIGURE:
  147.         return 1;
  148.     case ICM_CONFIGURE:
  149.     case ICM_ABOUT:
  150.         return ICERR_UNSUPPORTED;
  151.     case ICM_GETSTATE:
  152.         return 0L;
  153.     case ICM_GETINFO:
  154.         return AVIDrawGetInfo((ICINFO FAR *)lParam1, lParam2);
  155.     case ICM_DRAW_QUERY:
  156.         return AVIDrawQuery(pi, (LPBITMAPINFOHEADER)lParam1);
  157.     case ICM_DRAW_SUGGESTFORMAT:
  158.         return AVIDrawSuggestFormat(pi, (ICDRAWSUGGEST FAR *) lParam1, lParam2);
  159.     case ICM_DRAW_BEGIN:
  160.         return AVIDrawBegin(pi, (ICDRAWBEGIN FAR *) lParam1, lParam2);
  161.     case ICM_DRAW_REALIZE:
  162.         pi->hdc = (HDC) lParam1;
  163.         if (!pi->hdc || !pi->hdd)
  164.             break;
  165.         return DrawDibRealize(pi->hdd, pi->hdc, (BOOL) lParam2);
  166.     case ICM_DRAW_GET_PALETTE:
  167.         if (!pi->hdd)
  168.             break;
  169.         return (LONG) (UINT) DrawDibGetPalette(pi->hdd);
  170.     case ICM_DRAW:
  171.         return AVIDraw(pi, (ICDRAW FAR *)lParam1, lParam2);
  172.     case ICM_DRAW_CHANGEPALETTE:
  173.         return AVIDrawChangePalette(pi, (LPBITMAPINFOHEADER) lParam1);
  174.     case ICM_DRAW_END:
  175.         return AVIDrawEnd(pi);
  176.     case DRV_DISABLE:
  177.     case DRV_ENABLE:
  178.         return 1;
  179.     case DRV_INSTALL:
  180.     case DRV_REMOVE:
  181.         return 1;
  182.     }
  183.     if (uiMessage < DRV_USER)
  184.     {
  185.         return DefDriverProc(id,hDriver,uiMessage,lParam1,lParam2);
  186.     }
  187.     else
  188.     {
  189.         return ICERR_UNSUPPORTED;
  190.     }
  191. }
  192.  
  193.  
  194. // This basically allocates our "instance info" (that struct defined
  195. // at the beginning of this file).
  196. static LONG NEAR PASCAL AVIDrawOpen(ICOPEN FAR * icopen)
  197. {
  198.     PINSTINFO pinst;
  199.     if (icopen->fccType != streamtypeVIDEO)
  200.     {
  201.         return 0;
  202.     }
  203.     if (icopen->dwFlags == ICMODE_COMPRESS)
  204.     {
  205.         return 0;
  206.     }
  207.     if (icopen->dwFlags == ICMODE_DECOMPRESS)
  208.     {
  209.         return 0;
  210.     }
  211.     pinst = (PINSTINFO)GlobalAllocPtr(GHND, sizeof(INSTINFO));
  212.     if (!pinst)
  213.     {
  214.         icopen->dwError = ICERR_MEMORY;
  215.         return NULL;
  216.     }
  217.     pinst->hdd = DrawDibOpen();
  218.     pinst->hddb = NULL;
  219.     icopen->dwError = ICERR_OK;
  220.     return (LONG) pinst;
  221. }
  222.  
  223. // This frees our instance structure, and everything within the
  224. // structure.
  225. static LONG NEAR PASCAL AVIDrawClose(PINSTINFO pi)
  226. {
  227.     if (pi->hdd)
  228.     {
  229.         DrawDibClose(pi->hdd);
  230.     }
  231.     if (pi->hddb)
  232.     {
  233.         DisintegrateMemoryDC(pi);
  234.     }
  235.     GlobalFreePtr(pi);
  236.     return 1;
  237. }
  238.  
  239. // When AVI gets nosy, it goes here.  We pass it those strings and
  240. // stuff defined at the top of this file.
  241. static LONG NEAR PASCAL AVIDrawGetInfo(ICINFO FAR *icinfo, LONG lSize)
  242. {
  243.     if (icinfo == NULL)
  244.     {
  245.         return sizeof(ICINFO);
  246.     }
  247.     if (lSize < sizeof(ICINFO))
  248.     {
  249.         return 0;
  250.     }
  251.     icinfo->dwSize        = sizeof(ICINFO);
  252.     icinfo->fccType        = ICTYPE_VIDEO;
  253.     icinfo->fccHandler      = FOURCC_AVIDraw;
  254.     icinfo->dwFlags        = VIDCF_DRAW;
  255.     icinfo->dwVersion       = VERSION_AVIDraw;
  256.     icinfo->dwVersionICM    = ICVERSION;
  257.     lstrcpy(icinfo->szDescription, szDescription);
  258.     lstrcpy(icinfo->szName, szName);
  259.     return sizeof(ICINFO);
  260. }
  261.  
  262. // Make sure we can handle the format given.
  263. static LONG NEAR PASCAL AVIDrawQuery(PINSTINFO pi,
  264.     LPBITMAPINFOHEADER lpbiIn)
  265. {
  266.     if (lpbiIn == NULL)
  267.     {
  268.         return ICERR_BADFORMAT;
  269.     }
  270.     if (lpbiIn->biCompression != BI_RGB)
  271.     {
  272.         return ICERR_BADFORMAT;
  273.     }
  274.     return ICERR_OK;
  275. }
  276.  
  277. // suggest BI_RGB
  278. static LONG NEAR PASCAL AVIDrawSuggestFormat(PINSTINFO pi,
  279.     ICDRAWSUGGEST FAR *lpicd, LONG cbicd)
  280. {
  281.     HIC hic;
  282.     if (lpicd->lpbiSuggest == NULL)
  283.     {
  284.         return sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
  285.     }
  286.     hic = ICGetDisplayFormat(NULL, lpicd->lpbiIn, lpicd->lpbiSuggest,
  287.         0, lpicd->dxDst, lpicd->dyDst);
  288.     if (hic)
  289.     {
  290.         ICClose(hic);
  291.     }
  292.     if (lpicd->lpbiSuggest)
  293.     {
  294.         if (lpicd->lpbiSuggest->biCompression == BI_RLE8)
  295.         {
  296.             lpicd->lpbiSuggest->biCompression = BI_RGB;
  297.         }
  298.     }
  299.     return sizeof(BITMAPINFOHEADER) + lpicd->lpbiSuggest->biClrUsed * sizeof(RGBQUAD);
  300. }
  301.  
  302. // Here, we grab DC's and stuff from vfw and stash it into our own
  303. // instance info.  We also get our movieinfo, which is the structure
  304. // that has the actual hotspots in it.  It's in a global variable, even
  305. // though I don't like global variables...
  306. static LONG NEAR PASCAL AVIDrawBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd,
  307.     LONG cbicd)
  308. {
  309.     LONG    l;
  310.     l = AVIDrawQuery(pi, lpicd->lpbi);
  311.     if ((l != 0) || (lpicd->dwFlags & ICDRAW_QUERY))
  312.     {
  313.         return l;
  314.     }
  315.     pi->hdc = lpicd->hdc;
  316.     pi->xDst = lpicd->xDst;
  317.     pi->yDst = lpicd->yDst;
  318.     pi->dxDst = lpicd->dxDst;
  319.     pi->dyDst = lpicd->dyDst;
  320.     pi->xSrc = lpicd->xSrc;
  321.     pi->ySrc = lpicd->ySrc;
  322.     pi->dxSrc = lpicd->dxSrc;
  323.     pi->dySrc = lpicd->dySrc;
  324.     SetStretchBltMode(pi->hdc, COLORONCOLOR);
  325.     if (!DrawDibBegin(pi->hdd, pi->hdc,
  326.                 pi->dxDst, pi->dyDst,
  327.             lpicd->lpbi,
  328.             pi->dxSrc, pi->dySrc,
  329.             0))
  330.     {
  331.         return ICERR_UNSUPPORTED;
  332.     }
  333.     if (pi->hddb)
  334.     {
  335.         DisintegrateMemoryDC(pi);
  336.     }
  337.     CreateMemoryDC(pi);
  338.     pi->lpMovie = pMovieInfo;
  339.     return ICERR_OK;
  340. }
  341.  
  342. // Several interesting things happen here:  1) We copy the DIB onto
  343. // our own bitmap (hMemDC), with DrawDibDraw, then we draw rectangles
  344. // onto that bitmap (or not) as we walk down the hotspot list (with
  345. // Rectangle), then we BitBlt the result onto the screen.  I've heard
  346. // rumors that this could be done with the DIB driver and get rid of
  347. // the extra image copy.
  348. static LONG NEAR PASCAL AVIDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd)
  349. {
  350.     UINT  wFlags;
  351.     wFlags = DDF_SAME_HDC;
  352.     if ((lpicd->dwFlags & ICDRAW_NULLFRAME) || lpicd->lpData == NULL)
  353.     {
  354.         if (lpicd->dwFlags & ICDRAW_UPDATE)
  355.         {
  356.             wFlags |= DDF_UPDATE;
  357.         }
  358.         else
  359.         {
  360.             return ICERR_OK;
  361.         }
  362.     }
  363.     if (lpicd->dwFlags & ICDRAW_PREROLL)
  364.     {
  365.         wFlags |= DDF_DONTDRAW;
  366.     }
  367.     if (lpicd->dwFlags & ICDRAW_HURRYUP)
  368.     {
  369.         wFlags |= DDF_HURRYUP;
  370.     }
  371.     if (pi->lpMovie)
  372.     {
  373.         if(DrawDibDraw(pi->hdd, pi->hMemdc,
  374.                 0,0,
  375.                 pi->dxDst, pi->dyDst,
  376.                 lpicd->lpFormat,
  377.                 lpicd->lpData,
  378.                 pi->xSrc, pi->ySrc,
  379.                 pi->dxSrc, pi->dySrc,
  380.                 wFlags))
  381.         {
  382.             PHOTSPOT pHotspot;
  383.             pHotspot = (pi->lpMovie)->pHotspotList;
  384.             while (pHotspot)
  385.             {
  386.                 if ((pHotspot->BeginFrame <
  387.                     (lpicd->lTime)+1+(pi->lpMovie)->lLastSeek) &&
  388.                     (pHotspot->EndFrame > 
  389.                     (lpicd->lTime)-1+(pi->lpMovie)->lLastSeek))
  390.                 {
  391.                     Rectangle(pi->hMemdc,
  392.                         pHotspot->rc.left,
  393.                         pHotspot->rc.top,
  394.                         pHotspot->rc.right,
  395.                         pHotspot->rc.bottom);
  396.                 }
  397.                 pHotspot = pHotspot->pNext;
  398.             }
  399.             BitBlt(pi->hdc,pi->xDst,pi->yDst,pi->dxDst,pi->dyDst,
  400.                 pi->hMemdc,0,0,SRCCOPY);
  401.         }
  402.     }
  403.     else if (!DrawDibDraw(pi->hdd, pi->hdc,
  404.                 pi->xDst, pi->yDst,
  405.             pi->dxDst, pi->dyDst,
  406.             lpicd->lpFormat,
  407.             lpicd->lpData,
  408.             pi->xSrc, pi->ySrc,
  409.             pi->dxSrc, pi->dySrc,
  410.             wFlags))
  411.     {
  412.         if (wFlags & DDF_UPDATE)
  413.         {
  414.             return ICERR_CANTUPDATE;
  415.         }
  416.         else
  417.         {
  418.             return ICERR_UNSUPPORTED;
  419.         }
  420.     }
  421.     return ICERR_OK;
  422. }
  423.  
  424. // Give the pallette back to vfw with DrawDibChangePallette
  425. static LONG NEAR PASCAL AVIDrawChangePalette(PINSTINFO pi,
  426.     LPBITMAPINFOHEADER lpbi)
  427. {
  428.     PALETTEENTRY    ape[256];
  429.     LPRGBQUAD        lprgb;
  430.     int i;
  431.     lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize);
  432.     for (i = 0; i < (int) lpbi->biClrUsed; i++)
  433.     {
  434.         ape[i].peRed = lprgb[i].rgbRed;
  435.         ape[i].peGreen = lprgb[i].rgbGreen;
  436.         ape[i].peBlue = lprgb[i].rgbBlue;
  437.         ape[i].peFlags = 0;
  438.     }
  439.     DrawDibChangePalette(pi->hdd, 0, (int) lpbi->biClrUsed,
  440.         (LPPALETTEENTRY)ape);
  441.     return ICERR_OK;
  442. }
  443.  
  444. // Everything is freed in AVIDrawClose, nothing to do here...
  445. static LONG NEAR PASCAL AVIDrawEnd(PINSTINFO pi)
  446. {
  447.     return ICERR_OK;
  448. }
  449.